#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/time.h>
#include "HttpCgi.h"

namespace HttpFrame
{

int cgi_asyn_process(COperationEngine *pEngine, CHttpObject* phttp_object)
{
    if(NULL == pEngine || NULL == phttp_object)
    {
        return -1;
    }

    int nRet = 0;

    if(pEngine->ReqBuffer()==NULL||pEngine->RspBuffer()==NULL)
    {
        pEngine->Logger()->LOG_P(HF_LOG_ERROR,"cgi_process ReqBuffer==NULL||RspBuffer==NULL\n");
        return -2;
    }

    pEngine->ResetBuffer();

    ConnInfor_t conn;
    const char *pTmp = NULL;
    
    pTmp = phttp_object->getenv("SERVER_NAME");
    
    if(pTmp!=NULL)
    {
        struct hostent *he=gethostbyname(pTmp);
        if(he!=NULL&&*he->h_addr_list!=NULL)
        {
           conn.localip_ = ((struct in_addr*)(*he->h_addr_list))->s_addr;
        }
    }

    pTmp = phttp_object->getenv("REMOTE_ADDR");
    
    if(pTmp!=NULL)
    {
        conn.remoteip_ = inet_addr(pTmp);
    }

    pTmp = phttp_object->getenv("SERVER_PORT");
    
    if(pTmp!=NULL)
    {
        conn.localport_ = (unsigned short)atoi(pTmp);
    }

    pTmp = phttp_object->getenv("REMOTE_PORT");
    
    if(pTmp!=NULL)
    {
        conn.remoteport_ = (unsigned short)atoi(pTmp);
    }

    CAsynCgiHttpProtocolParse reqParase(pEngine->ReqBuffer(), \
                                        pEngine->ReqBufferSize(),\
                                        phttp_object, \
 		                                pEngine->CmdName().c_str(), \
 		                                pEngine->VersionName().c_str(), \
 		                                pEngine->ClientName().c_str(), \
 		                                pEngine->ServerName().c_str());

    CCgiHttpProtocolParse rspParase(pEngine->RspBuffer(), \
                                    pEngine->RspBufferSize(), \
 		                            pEngine->CmdName().c_str(), \
 		                            pEngine->VersionName().c_str(), \
 		                            pEngine->ClientName().c_str(), \
 		                            pEngine->ServerName().c_str());

    if(reqParase.ReadBody()!=0)
    {
        pEngine->Logger()->LOG_P(HttpFrame::Loger::LOG_ERROR,"Requst's body length(%d) is larger than max buffer length(%d) or read body fase!\n",reqParase.GetBodyLen(),reqParase.GetBufLen());
        rspParase.MakeRespone(400, "Bad Request ", 0, 0, NULL, 0);
        return 0;
    }

    pEngine->SetHandlerParam(phttp_object);
    
    nRet = pEngine->ProcessPack(&conn, reqParase, rspParase);

    if(nRet)
    {
        pEngine->Logger()->LOG_P(HF_LOG_ERROR,"nRet=%d,local_ip=%u,local_port=%u,"
                                 "remote_ip=%u,remote_port=%u,rsplen=%u\n", nRet, \
  	                             conn.localip_ ,conn.localport_,conn.remoteip_,   \
  	                             conn.remoteport_,rspParase.GetPackLen());

        return -3;
    }

    return 0;

}

int cgi_process(COperationEngine *pEngine)
{
    if(pEngine==NULL)
    {
        //pEngine->Logger()->LOG_P(HF_LOG_ERROR,"cgi_process pEngine==NULL\n");

        return -1;
    }
    struct timeval  t1,t2;
    memset(&t1,0,sizeof(t1));
    memset(&t2,0,sizeof(t2));
    
    gettimeofday(&t1,NULL);
    
    pEngine->Logger()->LOG_P(HF_LOG_DEBUG,"cgi_process,CmdName=%s,VersionName=%s,ClientName=%s,ServerName=%s\n"
    	       ,pEngine->CmdName().c_str()
 		,pEngine->VersionName().c_str()
 		,pEngine->ClientName().c_str()
 		,pEngine->ServerName().c_str());

    int nRet = 0;

    if(pEngine->ReqBuffer()==NULL||pEngine->RspBuffer()==NULL)
    {
        pEngine->Logger()->LOG_P(HF_LOG_ERROR,"cgi_process ReqBuffer==NULL||RspBuffer==NULL\n");
        return -2;
    }

    pEngine->ResetBuffer();

    //char **env = environ;
    //while(*env)
   // {
    //    pEngine->Logger()->LOG_P(HttpFrame::Loger::LOG_DEBUG,"%s\n",*env);
    //    ++env;
   // }
    
    ConnInfor_t conn;
    char *pTmp = NULL;
    pTmp=getenv("SERVER_NAME");
    if(pTmp!=NULL)
    {
        struct hostent *he=gethostbyname(pTmp);
        if(he!=NULL&&*he->h_addr_list!=NULL)
        {
           conn.localip_ = ((struct in_addr*)(*he->h_addr_list))->s_addr;
        }
    }

    pTmp=getenv("REMOTE_ADDR");
    if(pTmp!=NULL)
    {
        conn.remoteip_ = inet_addr(pTmp);
    }

    pTmp=getenv("SERVER_PORT");
    if(pTmp!=NULL)
    {
        conn.localport_ = (unsigned short)atoi(pTmp);
    }

    pTmp=getenv("REMOTE_PORT");
    if(pTmp!=NULL)
    {
        conn.remoteport_ = (unsigned short)atoi(pTmp);
    }
    
    //pEngine->Logger()->LOG_P(HttpFrame::Loger::LOG_ERROR,"cgi_process 3\n");
    
    CCgiHttpProtocolParse reqParase(pEngine->ReqBuffer(),pEngine->ReqBufferSize()
 		,pEngine->CmdName().c_str()
 		,pEngine->VersionName().c_str()
 		,pEngine->ClientName().c_str()
 		,pEngine->ServerName().c_str());

    //pEngine->Logger()->LOG_P(HttpFrame::Loger::LOG_ERROR,"cgi_process 4\n");
    reqParase.ConnInfo(&conn);
    //pEngine->Logger()->LOG_P(HttpFrame::Loger::LOG_ERROR,"cgi_process 5\n");
    
    CCgiHttpProtocolParse rspParase(pEngine->RspBuffer(),pEngine->RspBufferSize()
 		,pEngine->CmdName().c_str()
 		,pEngine->VersionName().c_str()
 		,pEngine->ClientName().c_str()
 		,pEngine->ServerName().c_str());

    gettimeofday(&t2,NULL);
    pEngine->Logger()->LOG_P(HttpFrame::Loger::LOG_DEBUG,"cgi_process befor readbody!time_use=%d\n",(t2.tv_sec-t1.tv_sec)*1000000+(t2.tv_usec-t1.tv_usec));
    
    if(reqParase.ReadBody()!=0)
    {
        pEngine->Logger()->LOG_P(HttpFrame::Loger::LOG_ERROR,"Requst's body length(%d) is larger than max buffer length(%d) or read body fase!\n",reqParase.GetBodyLen(),reqParase.GetBufLen());
        rspParase.MakeRespone(400, "Bad Request ", 0, 0, NULL, 0);
        return 0;
    }

    //pEngine->Logger()->LOG_P(HttpFrame::Loger::LOG_ERROR,"pEngine->ProcessPack\n");
    pEngine->Logger()->LOG_P(HttpFrame::Loger::LOG_DEBUG,"cgi_process after readbody!time_use=%d\n",(t2.tv_sec-t1.tv_sec)*1000000+(t2.tv_usec-t1.tv_usec));
    
    nRet = pEngine->ProcessPack(&conn, reqParase, rspParase);

   pEngine->Logger()->LOG_P(HF_LOG_DEBUG,"nRet=%d,local_ip=%u,local_port=%u,remote_ip=%u,remote_port=%u,rsplen=%u,data:%s\n"
  	                    ,nRet,conn.localip_ ,conn.localport_,conn.remoteip_,conn.remoteport_,rspParase.GetPackLen(),(char*)rspParase.GetData());

   gettimeofday(&t2,NULL);
   pEngine->Logger()->LOG_P(HttpFrame::Loger::LOG_DEBUG,"cgi_process after readbody!time_use=%d\n",(t2.tv_sec-t1.tv_sec)*1000000+(t2.tv_usec-t1.tv_usec));
   
    if(rspParase.GetPackLen()!=0)
    {
         nRet = write(1,rspParase.GetData(),rspParase.GetPackLen());
         pEngine->Logger()->LOG_P(HF_LOG_DEBUG,"write ret=",nRet);
    }

    gettimeofday(&t2,NULL);
    pEngine->Logger()->LOG_P(HttpFrame::Loger::LOG_DEBUG,"cgi_process after write!time_use=%d\n",(t2.tv_sec-t1.tv_sec)*1000000+(t2.tv_usec-t1.tv_usec));
   
    return 0;
    
}


}

